跳到主要内容

树莓派生产环境服务器

1 开机通网

参考:《树莓派4B家庭服务器搭建指南》刷Ubuntu Server 20.04并绑定公网域名,对公网提供http服务,通过公网进行SSH登录..._zhaoolee的博客-CSDN博客

1.1 系统盘准备

  1. 使用 SD Card Formatter 格式化内存卡

SD Memory Card Formatter for Windows/Mac | SD Association (sdcard.org)

选择分区,格式化即可

  1. 下载 Ubuntu Server 22.04.2 LTS 系统镜像

Install Ubuntu on a Raspberry Pi | Ubuntu

  1. 使用 balenaEtcher 将镜像烧录到 SD 卡

选择镜像文件 => 选择 SD 卡设备 => 开始烧录

烧录完成后,给树莓派设备插卡,插网线,开机!

烧录后使用 ubuntu 用户进入系统遇到了 Permission denied (publickey). 的问题

使用 rpi-imager GitHub - raspberrypi/rpi-imager: The home of Raspberry Pi Imager, a user-friendly tool for creating bootable media for Raspberry Pi devices.

可以设置默认账户和密码,并进行 ssh 或 wifi 等初始化配置

1.2 SSH 登录

  • 登录路由器后台获取树莓派内网 ip

  • 使用 SSH 登录服务器

ssh ubuntu@192.xxx.xxx.xxx

  • 如果使用 balenaEtcher 烧录的系统,那么初始账号密码均为 ubuntu,首次登录会强制修改默认密码
  • 登录后可以使用 sudo passwd root 重置 root 账户密码

1.2.1 ssh 管理平台下载

windows:xshell & xftp

家庭/学校免费 - NetSarang Website (xshell.com)

mac: Royal TSX

Royal TSX for Mac v5.1.2激活汉化版 强大的远程管理软件_马克喵 (macat.vip)

1.2.2 通过公网 ip 进行 ssh 连接

首先在路由器设置中绑定 ubuntu 的内网 ip 及 mac

然后开启路由器设置中的DMZ 主机功能,将 ubuntu 设备的 ip 地址设置为 DMZ 主机 ip 地址

后续进行安全配置后,仅支持公钥方式登录,因此远程软件也要配置用户密钥(记得上传私钥而不是公钥)

1.3 安全配置

1.3.1 新用户

1.3.2 ssh密钥对登录

Ubuntu 设置 SSH 通过密钥登录 - 知乎 (zhihu.com)

将常用远程设备的ssh公钥上传至服务器中

ssh-copy-id ubuntu@gsemir2.tpddns.cn

禁用默认账号密码登录

sudo vi /etc/ssh/sshd_config

PubkeyAuthentication yes
PermitRootLogin no
PasswordAuthentication no

记得看下 sshd_config.d 路径下的配置文件,因为其中的配置会将 sshd_config 的配置覆盖掉

重启 ssh 服务

sudo systemctl restart ssh

现在只有授权的电脑可以ssh登录服务器了

1.3.3 ufw 限制端口访问

How To Set Up a Firewall with UFW on Ubuntu 20.04 | DigitalOcean

Initial Server Setup with Ubuntu 20.04 | DigitalOcean

允许 ssh 连接:sudo ufw allow ssh

启动 ufw 服务(先允许 ssh 连接再启动):sudo ufw enable

查看当前开放的端口:sudo ufw status verbose

开放 vscode 远程 (ms-vscode-remote.vscode-remote-extensionpack) 接口:sudo ufw allow 41261 comment 'VSCODE'

开放 mysql 远程端口:sudo ufw allow 3306 comment 'MYSQL'

开放 psql 远程端口:sudo ufw allow 5432 comment 'PSQL'

然后重启系统即可 sudo systemctl reboot

1.4 科学上网

  1. windows 或 mac 使用 clashX 软件,开启系统代理允许局域网选项

  2. windows 需要在防火墙中新增 7890 端口的规则

    1. win + R 输入 wf.msc回车

    2. 入站规则 => 新建规则 => 端口 7890 => 允许连接 => 保存

  3. 远程 ubuntu server 中设置代理:export https_proxy=http://公网或内网 ip 地址:7890

  4. 测试代理设置 curl -I https://google.com

代理仅在当前当次会话生效

2 环境配置

2.0 nmon 性能监控

  1. 安装 nmon

    Ubuntu Server 24.04 的默认软件仓库中包含了 nmon 软件包, 你可以使用 apt 命令进行安装:

    sudo apt update
    sudo apt install nmon
  2. 运行 nmon

    安装完成后,在终端中输入 nmon 并回车即可启动 nmon:

    nmon

    nmon 将会以交互式模式启动,并显示一个包含各种系统性能指标的界面。

  3. 使用 nmon

    nmon 的界面简洁易懂,你可以使用键盘上的按键切换不同的监控指标:

    • c - CPU 使用率
    • m - 内存使用情况
    • d - 磁盘 I/O
    • n - 网络使用情况
    • k - 内核统计信息
    • j - 文件系统统计信息

    你可以同时按下多个按键来查看多个指标,例如按下 cm 就可以同时查看 CPU 和内存的使用情况.

  4. 保存 nmon 数据

    nmon 可以将监控数据保存到文件中,方便你进行后续分析。 你可以使用以下命令将数据保存到名为 performance.nmon 的文件中:

    nmon -f -t -s 2 -c 120 -F performance.nmon

    参数说明:

  • -f: 启用数据记录到文件的功能。
  • -t: 在输出的文件名中包含时间戳。
  • -s 2: 每隔 2 秒钟采集一次数据。
  • -c 120: 总共采集 120 次数据(也就是运行 2 分钟)。
  • -F performance.nmon: 指定输出文件名为 performance.nmon
  1. 分析 nmon 数据

    nmon 数据文件可以使用 nmon analyser 工具进行分析, 你可以从 nmon analyser 下载页面 下载该工具

2.1 源

ubuntu-ports | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror

  1. 备份
cd /etc/apt
sudo cp sources.list sources.list.bak
  1. 粘贴
sudo vi sources.list
  1. 更新配置
sudo apt update

关于命令的选择

apt > apt-get

systemctl > service

2.2 oh-my-zsh

How to Install Oh My Zsh on Ubuntu 20.04 to Boost Your Productivity - Cherry Servers

sudo apt update

# install zsh
sudo apt install -y zsh
# check zsh is installed successfully
which zsh
/usr/bin/zsh
# Maybe need to run zsh to install
zsh
# Make Zsh your default shell
sudo chsh -s /usr/bin/zsh
# If you are not root
chsh -s /usr/bin/zsh
# better restart your cmd
# check if zsh is default
echo $SHELL
/usr/bin/zsh

# If dont have curl
sudo apt install curl

# install oh-my-zsh
sudo sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# If you are not installing for root
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# uninstall
sudo sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/uninstall.sh)"

# add pre-built plugin
vi ~/.zshrc
plugin=(git history dirhistory)
# install custom plugin
# Autosuggestions Plugin
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

# Syntax Highlighting Plugin
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
vi ~/.zshrc
plugins=(
# other plugins...
zsh-autosuggestions
zsh-syntax-highlighting
)

如果之前一直使用 bash 作为默认 shell,那么需要 source ~/.bashrc 以继承环境变量等配置;最好写到 .zshrc 中,不然每次打开新的 shell 都要运行

2.3 nginx

How To Install Nginx on Ubuntu 20.04 | DigitalOcean

How To Deploy a React Application with Nginx on Ubuntu 20.04 | DigitalOcean

2.3.1 安装

  1. 安装
$ sudo apt update
$ sudo apt install nginx
  1. 调整防火墙
$ sudo ufw app list
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
$ sudo ufw reload # 重启
$ sudo ufw enable # 启动
# 启动防火墙后记得允许 OpenSSH 否则 SFTP 连接不上
$ sudo ufw allow 'Nginx HTTP'
$ sudo ufw status
Status: active

To Action From
-- ------ ----
Nginx HTTP ALLOW Anywhere
Nginx HTTP (v6) ALLOW Anywhere (v6)

2.3.2 部署流程

  1. 查看服务状态/启动/重启:

sudo service nginx status (old)

sudo systemctl status nginx(new)

sudo service nginx start (old)

sudo systemctl start nginx (new)

curl localhost 验证 nginx 服务启动

  1. 将项目文件放入静态资源目录

/var/www/project_name/html

将目录与子目录的文件的所有权设置为当前用户(读、写、删、执行)

sudo chown -R $USER:$USER /var/www/test_project_1/html

权限设置为读、写、执行权限(5只有读和执行权限)

sudo chmod -R 755 /var/www/test_project_1

  1. 配置

sudo vi /etc/nginx/sites-available/project_name

/etc/nginx/sites-available 相当于所有可用的项目配置文件,目录存放了每个虚拟主机的配置文件模板,通常以域名命名。

server {
# 监听 8080 端口(ipv4 和 ipv6)
listen 8080;
listen [::]:8080;
# 静态资源根目录
root /var/www/project_name/html;
# 设置默认文件的名称
index index.html index.htm index.nginx-debian.html;

# server_name test_project_1 www.test_project_1;
# 匹配到根目录时的配置
location / {
# 指令用于尝试查找指定的文件。它按照给定的顺序依次尝试 $uri 和 $uri/ 两个参数,并返回第一个存在的文件。如果都找不到,则返回HTTP状态码404。
try_files $uri $uri/ =404;
}
# 后端代理
location /api {
proxy_pass http://localhost:8888/api;
}
}
  1. 启用配置

将配置文件链接到 /etc/nginx/sites-enabled,表示启用该项目配置

sudo ln -s /etc/nginx/sites-available/project_name /etc/nginx/sites-enabled/

  1. 重启服务

检查nginx语法

sudo nginx -t

重启nginx

sudo service nginx restart

  1. 其他

nginx 错误日志

cat /var/log/nginx/error.log

2.3.3 前端项目部署脚本示例

function title {
echo
echo "###############################################################################"
echo "## $1"
echo "###############################################################################"
echo
}

user=ubuntu
ip=gsemir2.tpddns.cn
project_name=todo-frontend-vue
time=$(date +'%Y%m%d-%H%M%S')
# $0 表示当前脚本,用于 scp 复制所需的绝对路径
current_dir=$(dirname $0)
nginx_config_dir=$current_dir/$project_name
dist=$current_dir/dist
deploy_dir=/home/$user/deploys/frontend/$project_name/$time
nginx_html_dir=/var/www/$project_name/html
nginx_available_dir=/etc/nginx/sites-available
nginx_enabled_dir=/etc/nginx/sites-enabled

title '打包源代码'
pnpm run build
title '创建远程目录'
ssh $user@$ip "mkdir -p $deploy_dir"
title '上传 dist'
scp -r $dist/* $user@$ip:$deploy_dir
title '复制 nginx 静态文件'
ssh $user@$ip "sudo rm -rf $nginx_html_dir/*"
ssh $user@$ip "sudo cp -r $deploy_dir/* $nginx_html_dir/"
ssh $user@$ip "sudo chown -R $user:$user $nginx_html_dir"
ssh $user@$ip "sudo chmod -R 755 /var/www/$project_name"
title '上传 nginx 配置'
scp $nginx_config_dir $user@$ip:$nginx_available_dir/
title '启动配置'
ssh $user@$ip "sudo ln -s $nginx_available_dir/$project_name $nginx_enabled_dir"
title '启动 nginx 服务'
ssh $user@$ip "sudo systemctl restart nginx"
title '部署完毕'

2.2 sql

2.2.1 PostgreSQL

  • 安装
sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresql.service
  • 初始化

安装并启动后,并不能直接通过 psql 连接到 postgres 服务

因为 postgres 初始只有一名角色(postgres),目前的用户(ubuntu)是无法登录的

# 使用 postgres 用户身份运行一个新的 shell -i选项表示使用新的环境变量
sudo -i -u postgres
# 访问 postgres 服务
psql
# 进入服务后,先为我们的服务器管理账户 ubuntu 创建数据库的角色
CREATE USER ubuntu WITH PASSWORD 'xxx';
# 创建一个属于 ubuntu 角色的数据库,并设置权限
CREATE DATABASE ubuntu OWNER ubuntu;
# 将数据库所有权限赋给 ubuntu 用户
GRANT ALL PRIVILEGES ON DATABASE ubuntu to ubuntu;
# 给 ubuntu 用户添加 创建数据库 的属性
ALTER ROLE ubuntu CREATEDB;
# 之后就可以使用 ubuntu 用户来登录或创建并管理其他数据库了
  • 默认情况下,PostgreSQL 可能会仅监听本地连接 (127.0.0.1)。此时需要修改 PostgreSQL 配置文件 postgresql.conf
# 使用超级用户登录 postgres 服务
sudo -i -u postgres
psql
# 查看配置文件路径
SHOW config_file;
# /etc/postgresql/14/main/postgresql.conf
# 查看默认端口号
cat /etc/postgresql/14/main/postgresql.conf | grep 'port'
# 使用 postgres 用户 vi 编辑这个文件
# 找到`listen_addresses` 参数,将其设置为 `*` (监听所有接口) 或指定内网 IP 地址 (例如:`listen_addresses = 'localhost, 192.168.31.179'`)。
# 修改后,重启 PostgreSQL 服务:
sudo systemctl restart postgresql.service
  1. 使用超级用户编辑 pg_hba.conf 文件
sudo -i -u postgres
vi /etc/postgresql/16/main/pg_hba.conf
  1. 添加访问规则
# 允许远程 TCP/IP 连接,注意 user 表示数据库用户
host <database> or all <user> or all 192.168.31.117/32 md5
# 支持该网段下所有 ip 连接,address 一栏使用 192.168.31.0/24

2.2.2 MySQL

  • 安装
sudo apt update
sudo apt install mysql-server
  • 配置MySQL

安装MySQL后,您需要运行MySQL的安全脚本以更改一些默认的不够安全的选项。在终端中运行以下命令:

sudo mysql_secure_installation
  • 验证MySQL
sudo systemctl status mysql.service
  • 连接MySQL
sudo mysql
  • 配置网络连接

如果需要 MySQL 允许来自网络主机的连接,您可以编辑/etc/mysql/mysql.conf.d/mysqld.cnf文件,将bind-address指令更改为服务器的IP地址。如果是 127.0.0.1,则说明不允许远程连接。

  • 重启MySQL
sudo systemctl restart mysql.service
  • 设置账号密码登录,并添加 ubuntu 账户
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
CREATE USER 'ubuntu'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
GRANT ALL PRIVILEGES ON *.* TO 'ubuntu'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
  • 授予特定主机连接权限
GRANT ALL PRIVILEGES ON *.* TO 'ubuntu'@'172.17.0.2' WITH GRANT OPTION;

2.3 node

  • 安装 nvm

https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script

  • curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

安装完成后,检查下下面的指令是否在 ~/.bashrc, ~/.profile, or ~/.zshrc 中,没有则复制过去

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
  • nvm install --lts

以上两条命令都需要科学上网

  • 配置 npm 源

npm set registry http://registry.npmmirror.com

2.4 Ruby

2.4.1 rbenv

不想用 rvm 了,在 aarch 架构的 cpu 下配置 ruby 环境太麻烦了。。改用 rbenv

How To Install Ruby on Rails with rbenv on Ubuntu 22.04 | DigitalOcean

sudo apt update
# 安装必要的库
sudo apt install libssl-dev libreadline-dev zlib1g-dev autoconf bison build-essential libyaml-dev libreadline-dev libncurses5-dev libffi-dev libgdbm-dev
# 使用 bash 安装 rbenv
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash
# 添加 rbenv 命令到环境变量
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
# 自动加载 rbenv 命令
echo 'eval "$(rbenv init -)"' >> ~/.zshrc
source ~/.zshrc
# 安装 ruby-3.0.0
rbenv install 3.0.0
# 指定默认版本
rbenv global 3.0.0
ruby -v # 3.0.0
# gem 配置
echo "gem: --no-document" > ~/.gemrc
# 安装 bundler
gem install bundler
# 查看 gem 路径
gem env home
# 安装 rails 7.0.2.3
gem install rails -v 7.0.2.3
# 在每次更新或安装 ruby 或 rails 时执行
rbenv rehash
rails -v
# 更新 rbenv
cd ~/.rbenv
git pull
# 卸载 ruby
rbenv uninstall 3.0.0
# 卸载 rbenv
# 删除 .zshrc 中的关于 rbenv 的代码
rm -rf `rbenv root`

2.5 Docker

2.5.1 Docker

  • 安装

https://docs.docker.com/engine/install/ubuntu/

按照文档走即可

把 ubuntu 用户加入 docker 组中:sudo usermod -a -G docker ubuntu

  • 配置

在用户的主目录下创建一个名为.docker的文件夹:mkdir ~/.docker

.docker文件夹中创建一个名为config.json的文件:touch ~/.docker/config.json

{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"https://registry.cn-hangzhou.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://registry.docker-cn.com",
"https://mirror.ccs.tencentyun.com"
]
}
  • 启动 docker 服务:sudo systemctl start docker
  • 允许 docker 开机启动 sudo systemctl enable docker
  • 看容器日志:docker container logs [CONTAINER]

2.5.2 安装 Docker Compose

2.6 Go

2.6.1 ubuntu 22.04 aarch64

# 下载安装包
curl -OL https://golang.org/dl/go1.21.0.linux-arm64.tar.gz
# 解压
sudo tar -C /usr/local -xvf go1.21.0.linux-arm64.tar.gz
# ~/.zshrc 添加环境变量
export PATH=$PATH:/usr/local/go/bin
# 验证安装
go version

2.6.2 配置代理

go env -w GOPROXY=https://goproxy.cn,direct

go env GOPROXY 查看当前代理

2.7 Git

git config --global user.name "gsemir0418"
git config --global user.email "845217811@qq.com"
ssh-keygen -t rsa -C "845217811@qq.com"
cd ~/.ssh/
cat id_rsa.pub

2.8 aapanel 安装

aaPanel - Free and Open source Hosting control panel. One-click LAMP/LEMP.

su root 切换到 root 执行安装命令即可,大概30分钟左右安装完成

完成后复制控制台最后几行配置

Congratulations! Installed successfully!
==================================================================
aaPanel Internet Address: https://122.233.10.200:28987/3f57bdd8
aaPanel Internal Address: https://192.168.31.177:28987/3f57bdd8
username: lxhgv3m1
password: 15a2bed0
Warning:
If you cannot access the panel,
release the following port (28987|888|80|443|20|21) in the security group

可以登录后,在 Settings 中重设用户名和密码

3 外接硬盘

查看移动硬盘

sudo fdisk -l

可以看到下图

Disk /dev/loop0: 33.65 MiB, 35287040 bytes, 68920 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/loop1: 33.71 MiB, 35344384 bytes, 69032 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/mmcblk0: 29.73 GiB, 31927042048 bytes, 62357504 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0529037a

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 * 2048 1050623 1048576 512M c W95 FAT32 (LBA)
/dev/mmcblk0p2 1050624 62357470 61306847 29.2G 83 Linux


Disk /dev/sda: 223.57 GiB, 240057409536 bytes, 468862128 sectors
Disk model: SA400S37240G
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 33553920 bytes
Disklabel type: gpt
Disk identifier: 5DC5357B-307C-4C7E-93B3-EEA64A94B6F2

Device Start End Sectors Size Type
/dev/sda1 4096 618495 614400 300M EFI System
/dev/sda2 618496 880639 262144 128M Microsoft reserved
/dev/sda3 880640 468862094 467981455 223.2G Microsoft basic data

/dev/sda3 就是挂载的移动硬盘的盘符(238GB)

创建移动硬盘要挂载的目录

sudo mkdir /media/ssd

给与要挂载的目录权限

sudo chmod 777 /media/ssd

挂载移动硬盘到指定目录

/dev/sda3 为移动硬盘的盘符

mount -o rw /dev/sda3 /media/ssd

因为移动硬盘之前是在window系统下使用快速格式化为NTFS系统

显示在linux识别系统有问题,需要重新格式化

sudo ntfsfix /dev/sda3

可能会提示以下错误

Mount is denied because the NTFS volume is already exclusively opened.The volume may be already mounted, or another software may use it whichcould be identified for example by the help of the 'fuser' command.

因为之前尝试挂载过一次,但是挂载过程中出现错误

这里先尝试卸载挂载的移动硬盘

umount /media/ssd

然后再次尝试重新挂载

后续直接把文件和数据存放在 /media/ssd 目录即可

其他

filebrowser

常用命令

curl ifconfig.me 获取公网ip

sudo ss -tuln | grep 8080 查看8080端口是否有服务占用

| 管道符号,将前一个命令的标准输出作为后一个命令的输入

grep 文本搜索工具,在给定的文件或标准输入中查找匹配指定模式的行,并打印出来

nginx 文件系统

sudo ufw allow 8081 comment 'nginx-file-server'

sudo systemctl restart nginx

server {
listen 8081;
server_name _;
root /media/ssd/btm_images;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;

location / {
try_files $uri $uri/ =404;
}

allow 192.168.31.0/16;
deny all;
}

sudo nginx -t

sudo ln -s /etc/nginx/sites-available/btm-images /etc/nginx/sites-enabled/

sudo systemctl reboot

http://192.168.31.176:8081/someimage.png